# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------



# ----------------------------------------------------------------------------
# Use to receive RF events
# from Rfxcom 433 receiver
# Receiving data / USB Serial
# Python version 2.7.x and 3.x
# ----------------------------------------------------------------------------
# Software HEYU
# -------------
# - Website: http://www.heyu.org
# - HEYU is used as base for development of scripts
#
# Software AnyEvent-RFXCOM
# ------------------------
# - Website: http://search.cpan.org/dist/AnyEvent-RFXCOM/
# - AnyEvent-RFXCOM is used as base for development of scripts
# ----------------------------------------------------------------------------


import logging
from .devcomm.devserial import DEVserial
from .ctrlfcts.rfxcomfct import (requestcmd)

logger = logging.getLogger()


class RFXCOM(DEVserial):

    def __init__(self,port=None):
        DEVserial.__init__(self,port)
        self.idcontroller = 'RFXCOM'
        self.port = port
        self._baudrate = 4800
        self._interCharTimeout = 0.03
        self.setup = False
        self.TXcap = False
        self.RXcap = True

    def tsetup(self):
        """
        Setup interface with request version test
        """
        self.open()
        if not self.opened:
            return False
        logger.debug("Starting %s with Version request....",self.idcontroller)
        self.flush()
        data = self.request('VERS')
        if data is None:
            logger.warning("No response to request Version from controller...")
            self.opened = False
        elif data[0] in ('0x4d','0x53') :
            logger.warning("Success to request Version with response %s...",repr(data))
            self.flush()
            logger.warning("%s Ready....",self.idcontroller)
            self.setup = True
            self.device = self.idcontroller + '-' + self.port
        else:
            logger.warning("Response of controller not recognized %s...",repr(data))
            #self.opened = False
            self.setup = True
            self.device = self.idcontroller + '-' + self.port

    def flush(self):
        logger.debug("Flush buffer by reading %s...",self.idcontroller)
        n = 0
        while n < 5:
            res = self.read()
            if not res:
                n += 1
        return True

    def request(self,rcmd):
        return requestcmd(self,rcmd)

    def plsend(self):
        return None

    def rfsend(self):
        return None

    def rfxevents(self,minlen=4,maxlen=20,nloop=10,allevt=False,onlyrejected=False):
        """
        Read all events
        event = string (list of words in hexa)
        hd : first byte / header of event / lenght of event
        minlen = min lenght of event default = 4 bytes
        maxlen = max lenght of event default = 20 bytes
        nloop : number loop of pause before reject the event default = 10
        tsleep : pause sleep between interrupts default = 0.05 second
        allevt : True return also rejected event, default = False
        onlyrejected : True return rejected event only, default = False
        """
        hd = self.read()
        if not hd:
            return None
        nbits  = hd & 0x7F
        nbytes = int((nbits + 7) / 8)
        hdh = "0x%02x" % hd
        if nbytes > maxlen:
            logger.warning("Header read %s for the buffer have nbytes (%s) greater than max lenght (%s), reject this read", hd, nbytes,maxlen)
            if allevt :
                return 'HEADER_GT_MAX ' + hdh
            else:
                return None
        event = [hdh]
        n = 0
        while n < nloop:
            data = self.readh()
            if data:
                event.append(data)
                if len(event) == nbytes + 1:
                    break
            else:
                n += 1
        if n > nloop:
            logger.warning("Event having number %s interrupts greater nloop %s",str(n),str(nloop))
            if allevt :
                return 'REJECTED ' + " ".join(event)
            else:
                return None
        if len(event) < minlen:
            logger.warning("Event len %s shorter than min size (%s) for incoming event omitting this read",str(len(event)),minlen)
            if allevt :
                return 'TOOSHORT' + " ".join(event)
            else:
                return None
        else:
            if onlyrejected :
                return None
            else:
                return " ".join(event)

    def rxevent(self,minlen=4,maxlen=25,nloop=10,cut=False):
        """
        Read one event after flush/pause
        event = string (list of words in hexa)
        hd : first byte / header of event / lenght of event
        minlen = min lenght of event default = 4 bytes
        maxlen = max lenght of event default = 20 bytes
        nloop : number loop of pause before reject the event default = 10
        tsleep : pause sleep between interrupts default = 0.05 second
        Cut down in case of duplicate events in one packet
        """
        hd = self.read()
        if not hd:
            return None
        nbits  = hd & 0x7F
        nbytes = int((nbits + 7) / 8)
        if nbytes > maxlen:
            logger.warning("Header read %s for the buffer have nbytes (%s) greater than max lenght (%s), reject this read", hd, nbytes,maxlen)
            return None
        hdh = "0x%02x" % hd
        event = [hdh]
        n = 0
        while n < nloop:
            data = self.readh()
            if data:
                event.append(data)
                if len(event) == nbytes + 1:
                    break
            else:
                n += 1
        if n > nloop:
            logger.warning("Event having number %s interrupts greater nloop %s",str(n),str(nloop))
        if len(event) < minlen:
            logger.warning("Event len %s shorter than min size (%s) for incoming event omitting this read",str(len(event)),minlen)
            return None
        if cut:
            evt = event
            d = evt.count(hdh)
            logger.warning("Test for cut down event, find %s time(s) header %s..",str(d),hdh)
            if d > 1:
                 nb = int(len(evt) / d)
                 if nb == nbytes + 1:
                      logger.warning("Cut down event %s",repr(evt))
                      event = evt[0:nb]
        return " ".join(event)
